﻿using System;
using System.Collections.Generic;
using NetTopologySuite.Index;
using NetTopologySuite.Index.Chain;
using NetTopologySuite.Index.Strtree;

namespace NetTopologySuite.Noding
{
	public class MCIndexNoder : SinglePassNoder
	{
		public MCIndexNoder()
		{
		}

		public MCIndexNoder(ISegmentIntersector segInt) : base(segInt)
		{
		}

		public IList<MonotoneChain> MonotoneChains
		{
			get
			{
				return this._monoChains;
			}
		}

		public ISpatialIndex<MonotoneChain> Index
		{
			get
			{
				return this._index;
			}
		}

		public override IList<ISegmentString> GetNodedSubstrings()
		{
			return NodedSegmentString.GetNodedSubstrings(this._nodedSegStrings);
		}

		public override void ComputeNodes(IList<ISegmentString> inputSegStrings)
		{
			this._nodedSegStrings = inputSegStrings;
			foreach (ISegmentString segStr in inputSegStrings)
			{
				this.Add(segStr);
			}
			this.IntersectChains();
		}

		private void IntersectChains()
		{
			MonotoneChainOverlapAction mco = new MCIndexNoder.SegmentOverlapAction(base.SegmentIntersector);
			foreach (MonotoneChain monotoneChain in this._monoChains)
			{
				foreach (MonotoneChain monotoneChain2 in this._index.Query(monotoneChain.Envelope))
				{
					if (monotoneChain2.Id > monotoneChain.Id)
					{
						monotoneChain.ComputeOverlaps(monotoneChain2, mco);
						this._nOverlaps++;
					}
					if (base.SegmentIntersector.IsDone)
					{
						return;
					}
				}
			}
		}

		private void Add(ISegmentString segStr)
		{
			foreach (MonotoneChain monotoneChain in MonotoneChainBuilder.GetChains(segStr.Coordinates, segStr))
			{
				MonotoneChain monotoneChain2 = monotoneChain;
				int idCounter = this._idCounter;
				this._idCounter = idCounter + 1;
				monotoneChain2.Id = idCounter;
				this._index.Insert(monotoneChain.Envelope, monotoneChain);
				this._monoChains.Add(monotoneChain);
			}
		}

		private readonly List<MonotoneChain> _monoChains = new List<MonotoneChain>();

		private readonly ISpatialIndex<MonotoneChain> _index = new STRtree<MonotoneChain>();

		private int _idCounter;

		private IList<ISegmentString> _nodedSegStrings;

		private int _nOverlaps;

		public class SegmentOverlapAction : MonotoneChainOverlapAction
		{
			public SegmentOverlapAction(ISegmentIntersector si)
			{
				this._si = si;
			}

			public override void Overlap(MonotoneChain mc1, int start1, MonotoneChain mc2, int start2)
			{
				ISegmentString e = (ISegmentString)mc1.Context;
				ISegmentString e2 = (ISegmentString)mc2.Context;
				this._si.ProcessIntersections(e, start1, e2, start2);
			}

			private readonly ISegmentIntersector _si;
		}
	}
}
